package com.itcast.peft.service;

import java.io.File;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Map;
import java.util.Optional;
import java.util.Random;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringSubstitutor;
import org.springframework.ai.converter.BeanOutputConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import com.itcast.peft.config.MultipleModelConfig.ChatModelHolder;
import com.itcast.peft.entity.report.HealthReportVo;
import com.itcast.peft.util.PDFUtil;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.Data;

@Service
public class HealthReportAnalyzer {
    
    @Resource
    private ChatModelHolder healthOptModelHolder;
    
    @Autowired
    private QuestionService questionService;
    
    private String messageTemplate;
    
    @PostConstruct
    void init() {
        messageTemplate = """
                请分析这份体检报告，报告中包含了一些异常数据，我需要您对这些数据进行解读，并给出相应的健康建议
                体检内容如下：${content}
                要求：
                提取体检报告中的“总检日期”
                通过临床医学、疾病风险评估模型和数据智能分析，给该用户的风险等级和健康指数给出结果。风险等级分为：健康、提示、风险、危险、严重危险。健康指数范围为0至100分；
                根据用户身体各项指标数据，详细说明该用户各项风险等级的占比是多少，最多保留两位小数。结论格式：该用户健康占比20.00%，提示占比20.00%，风险占比20%，危险占比20%，严重危险占比20%
                对于体检报告有异常数据，请列出（异常数据的结论、体检项目名称、检查结果、参考值、单位、异常解读、建议）这8字段。解读异常数据，解决这些数据可能代表的健康问题或风险。分析可能的原因，包括但不限于生活习惯、饮食习惯、遗传因素等。基于这些异常数据和可能的原因，请给出具体的健康建议，包括饮食调整、运动建议、生活方式改变以及是否需要进一步检查或治疗等。
                结论格式：异常数据的结论：肥胖，体检项目名称：体重指数BMI，检查结果：29.2，参考值>24，单位：-。异常解读：体重超标包括超重与肥胖。体重指数（BMI）=体重（kg）/身⾼（m）的平⽅，BMI≥24为超重，BMI≥28为肥胖；男性腰围≥90cm和⼥性腰围≥85cm为腹型肥胖。体重超标是⼀种由多因素（如遗传、进⻝油脂较多、运动少、疾病等）引起的慢性代谢性疾病，尤其是肥胖，已经被世界卫⽣组织列为导致疾病负担的⼗⼤危险因素之⼀。AI建议：采取综合措施预防和控制体重，积极改变⽣活⽅式，宜低脂、低糖、⾼纤维素膳⻝，多⻝果蔬及菌藻类⻝物，增加有氧运动。若有相关疾病（如⾎脂异常、⾼⾎压、糖尿病等）应积极治疗。
                根据这个体检报告的内容，分别是给人体的8大系统打分，每项满分为100分，8大系统分别为：呼吸系统、消化系统、内分泌系统、免疫系统、循环系统、泌尿系统、运动系统、感官系统
                给体检报告做一个总结，总结格式：体检报告中尿蛋⽩、癌胚抗原、⾎沉、空腹⾎糖、总胆固醇、⽢油三酯、低密度脂蛋⽩胆固醇、⾎清载脂蛋⽩B、动脉硬化指数、⽩细胞、平均红细胞体积、平均⾎红蛋⽩共12项指标提示异常，尿液常规共1项指标处于临界值，⾎脂、⾎液常规、尿液常规、糖类抗原、⾎清酶类等共43项指标提示正常，综合这些临床指标和数据分析：肾脏、肝胆、⼼脑⾎管存在隐患，其中⼼脑⾎管有“⾼危”⻛险；肾脏部位有“中危”⻛险；肝胆部位有“低危”⻛险。
                所有浮点型数据统一保留两位小数
                    """;
        
    }
    
    /**
     * 将PDF内容转换为字符串，存储入Question结构
     */
    @Async
    public void generateQuestionByPDF() {
        var converter = new BeanOutputConverter<>(HealthReportVo.class);
        var root = new File(HealthPDFGenerator.PDF_FOLDER);
        var sub = Optional.ofNullable(root.listFiles()).orElseThrow();
        var pdfList = Arrays.stream(sub).filter(f -> f.getName().toLowerCase().endsWith("pdf")).toList();
        var pdfStrList = pdfList.stream()
                .map(PDFUtil::pdfToString)
                .filter(StringUtils::isNotBlank)
                .map(c -> StringSubstitutor.replace(messageTemplate, Map.of("content", c), "${", "}"))
                .map(c -> withStructOutputSchema(c, converter.getFormat()))
                .toList();
        var trainData = new LinkedList<String>();
        var testData = new LinkedList<String>();
        var rand = new Random();
        pdfStrList.forEach(s -> {
            var lst = rand.nextInt(100) > 70 ? testData : trainData;
            lst.add(s);
        });
        // 分流：70%训练 30%测试
        questionService.addPDFDataAsQuestion(trainData);
        questionService.addPDFDataAsQuestion(testData);
    }
    
    private String withStructOutputSchema(String original,String format) {
        return original + System.lineSeparator() + format;
    }
    
    @Data
    public static class HealthData {
        Long questionId;
        String reportJson;
    }
}
